<script setup lang="ts">
import type { Rule } from 'ant-design-vue/es/form';

import type { Ref } from 'vue';

import { computed, inject, reactive, ref } from 'vue';

import { IconifyIcon, Plus, Trash2 } from '@vben/icons';
import { cloneDeep } from '@vben/utils';

import {
  Card,
  Col,
  Form,
  FormItem,
  Input,
  Radio,
  RadioGroup,
  Row,
  Select,
  SelectOption,
  Space,
  Switch,
  Textarea,
  Tooltip,
} from 'ant-design-vue';

import { BpmModelFormType } from '#/utils';

import {
  COMPARISON_OPERATORS,
  CONDITION_CONFIG_TYPES,
  ConditionType,
  DEFAULT_CONDITION_GROUP_VALUE,
} from '../../../consts';
import { useFormFieldsAndStartUser } from '../../../helpers';

defineOptions({
  name: 'Condition',
});

const props = defineProps({
  modelValue: {
    type: Object,
    required: true,
  },
});

const emit = defineEmits(['update:modelValue']);

const condition = computed({
  get() {
    return props.modelValue;
  },
  set(newValue) {
    emit('update:modelValue', newValue);
  },
});

const formType = inject<Ref<number>>('formType'); // 表单类型
const conditionConfigTypes = computed(() => {
  return CONDITION_CONFIG_TYPES.filter((item) => {
    // 业务表单暂时去掉条件规则选项
    return !(
      formType?.value === BpmModelFormType.CUSTOM &&
      item.value === ConditionType.RULE
    );
  });
});

/** 条件规则可选择的表单字段 */
const fieldOptions = useFormFieldsAndStartUser();

// 表单校验规则
const formRules: Record<string, Rule[]> = reactive({
  conditionType: [
    { required: true, message: '配置方式不能为空', trigger: 'change' },
  ],
  conditionExpression: [
    {
      required: true,
      message: '条件表达式不能为空',
      trigger: ['blur', 'change'],
    },
  ],
});

const formRef = ref(); // 表单 Ref

/** 切换条件配置方式 */
function changeConditionType() {
  if (
    condition.value.conditionType === ConditionType.RULE &&
    !condition.value.conditionGroups
  ) {
    condition.value.conditionGroups = cloneDeep(DEFAULT_CONDITION_GROUP_VALUE);
  }
}

function deleteConditionGroup(conditions: any, index: number) {
  conditions.splice(index, 1);
}

function deleteConditionRule(condition: any, index: number) {
  condition.rules.splice(index, 1);
}

function addConditionRule(condition: any, index: number) {
  const rule = {
    opCode: '==',
    leftSide: undefined,
    rightSide: '',
  };
  condition.rules.splice(index + 1, 0, rule);
}

function addConditionGroup(conditions: any) {
  const condition = {
    and: true,
    rules: [
      {
        opCode: '==',
        leftSide: undefined,
        rightSide: '',
      },
    ],
  };
  conditions.push(condition);
}

async function validate() {
  if (!formRef.value) return false;
  return await formRef.value.validate();
}

defineExpose({ validate });
</script>
<template>
  <Form
    ref="formRef"
    :model="condition"
    :rules="formRules"
    :label-col="{ span: 24 }"
    :wrapper-col="{ span: 24 }"
  >
    <FormItem label="配置方式" name="conditionType">
      <RadioGroup
        v-model:value="condition.conditionType"
        @change="changeConditionType"
      >
        <Radio
          v-for="(dict, indexConditionType) in conditionConfigTypes"
          :key="indexConditionType"
          :value="dict.value"
        >
          {{ dict.label }}
        </Radio>
      </RadioGroup>
    </FormItem>
    <FormItem
      v-if="
        condition.conditionType === ConditionType.RULE &&
        condition.conditionGroups
      "
    >
      <div class="mb-5 flex w-full justify-between">
        <div class="flex items-center">
          <div class="mr-4">条件组关系</div>
          <Switch
            v-model:checked="condition.conditionGroups.and"
            checked-children="且"
            un-checked-children="或"
          />
        </div>
      </div>
      <Space direction="vertical" size="small" class="w-11/12 pl-1">
        <template #split>
          {{ condition.conditionGroups.and ? '且' : '或' }}
        </template>
        <Card
          class="group relative w-full hover:border-blue-500"
          v-for="(equation, cIdx) in condition.conditionGroups.conditions"
          :key="cIdx"
        >
          <div
            class="absolute left-0 top-0 z-[1] flex cursor-pointer opacity-0 group-hover:opacity-100"
            v-if="condition.conditionGroups.conditions.length > 1"
          >
            <IconifyIcon
              color="blue"
              icon="lucide:circle-x"
              class="size-4"
              @click="
                deleteConditionGroup(condition.conditionGroups.conditions, cIdx)
              "
            />
          </div>
          <template #extra>
            <div class="flex items-center justify-between">
              <div>条件组</div>
              <div class="flex">
                <div class="mr-4">规则关系</div>
                <Switch
                  v-model:checked="equation.and"
                  checked-children="且"
                  un-checked-children="或"
                />
              </div>
            </div>
          </template>

          <Row
            :gutter="8"
            class="mb-2"
            v-for="(rule, rIdx) in equation.rules"
            :key="rIdx"
          >
            <Col :span="8">
              <FormItem
                :name="[
                  'conditionGroups',
                  'conditions',
                  cIdx,
                  'rules',
                  rIdx,
                  'leftSide',
                ]"
                :rules="{
                  required: true,
                  message: '左值不能为空',
                  trigger: 'change',
                }"
              >
                <Select
                  v-model:value="rule.leftSide"
                  allow-clear
                  placeholder="请选择表单字段"
                >
                  <SelectOption
                    v-for="(field, fIdx) in fieldOptions"
                    :key="fIdx"
                    :label="field.title"
                    :value="field.field"
                    :disabled="!field.required"
                  >
                    <Tooltip
                      title="表单字段非必填时不能作为流程分支条件"
                      placement="right"
                      v-if="!field.required"
                    >
                      <span>{{ field.title }}</span>
                    </Tooltip>
                    <template v-else>{{ field.title }}</template>
                  </SelectOption>
                </Select>
              </FormItem>
            </Col>
            <Col :span="6">
              <Select v-model:value="rule.opCode" placeholder="请选择操作符">
                <SelectOption
                  v-for="operator in COMPARISON_OPERATORS"
                  :key="operator.value"
                  :label="operator.label"
                  :value="operator.value"
                >
                  {{ operator.label }}
                </SelectOption>
              </Select>
            </Col>
            <Col :span="7">
              <FormItem
                :name="[
                  'conditionGroups',
                  'conditions',
                  cIdx,
                  'rules',
                  rIdx,
                  'rightSide',
                ]"
                :rules="{
                  required: true,
                  message: '右值不能为空',
                  trigger: ['blur', 'change'],
                }"
              >
                <Input
                  v-model:value="rule.rightSide"
                  placeholder="请输入右值"
                />
              </FormItem>
            </Col>
            <Col :span="3">
              <div class="flex h-8 items-center">
                <Trash2
                  v-if="equation.rules.length > 1"
                  class="mr-2 size-4 cursor-pointer text-red-500"
                  @click="deleteConditionRule(equation, rIdx)"
                />
                <Plus
                  class="size-4 cursor-pointer text-blue-500"
                  @click="addConditionRule(equation, rIdx)"
                />
              </div>
            </Col>
          </Row>
        </Card>
      </Space>
      <div title="添加条件组" class="mt-4 cursor-pointer">
        <Plus
          class="size-6 text-blue-500"
          @click="addConditionGroup(condition.conditionGroups?.conditions)"
        />
      </div>
    </FormItem>
    <FormItem
      v-if="condition.conditionType === ConditionType.EXPRESSION"
      label="条件表达式"
      name="conditionExpression"
    >
      <Textarea
        v-model:value="condition.conditionExpression"
        placeholder="请输入条件表达式"
        allow-clear
        :auto-size="{ minRows: 3, maxRows: 6 }"
      />
    </FormItem>
  </Form>
</template>
